package crmdna.list;

import static crmdna.common.AssertUtils.ensure;
import static crmdna.common.AssertUtils.ensureNotNull;
import static crmdna.common.OfyService.ofy;

import java.util.List;

import com.googlecode.objectify.Key;

import crmdna.common.APIException;
import crmdna.common.APIResponse.Status;
import crmdna.common.Utils;
import crmdna.sequence.Sequence;
import crmdna.sequence.Sequence.SequenceType;

public class ListCore {

	static ListProp create(String namespace, long groupId, String displayName,
			boolean restricted, boolean enabled) {

		ensureNotNull(namespace, "namespace is null");
		ensure(namespace.length() != 0, "namespace is empty");

		ensureNotNull(displayName, "displayName is null");
		ensure(displayName.length() != 0, "displayName is empty");

		String name = Utils.removeSpacesAndHyphen(displayName);

		List<Key<ListEntity>> keys = ofy(namespace).load()
				.type(ListEntity.class).filter("name", name)
				.filter("groupId", groupId).keys().list();

		if (keys.size() != 0)
			throw new APIException(Status.ERROR_RESOURCE_ALREADY_EXISTS,
					"There is already a list with name [" + displayName
							+ "] for group [" + groupId + "]");

		ListEntity entity = new ListEntity();
		entity.listId = Sequence.getNext(namespace, SequenceType.LIST);
		entity.name = name;
		entity.displayName = displayName;
		entity.groupId = groupId;
		entity.restricted = restricted;
		entity.enabled = enabled;

		ofy(namespace).save().entity(entity).now();
		return entity.toProp();
	}

	public static ListEntity safeGet(String namespace, long listId) {

		ensureNotNull(namespace, "namespace is null");
		ensure(namespace.length() != 0, "namespace is empty");
		ensure(listId != 0, "listId is 0");

		ListEntity entity = ofy(namespace).load().type(ListEntity.class)
				.id(listId).get();
		if (null == entity)
			throw new APIException(Status.ERROR_RESOURCE_NOT_FOUND,
					"List id  [" + listId + "] does not exist");

		return entity;
	}

	static ListProp update(String namespace, long listId,
			String newDisplayName, Long newGroupId, Boolean newRestricted,
			Boolean newEnabled) {

		ensureNotNull(namespace, "namespace is null");
		ensure(namespace.length() != 0, "namespace is empty");
		ensure(listId != 0, "listId is 0");

		ListEntity entity = safeGet(namespace, listId);

		// return if no changes
		if (newDisplayName == null)
			if (newGroupId == null)
				if (newRestricted == null)
					if (newEnabled == null)
						return entity.toProp();

		String newName = entity.name;
		if (newDisplayName != null) {
			ensure(newDisplayName.length() != 0, "displayName is empty");
			newName = Utils.removeSpacesAndHyphen(newDisplayName);
		}

		if (newGroupId == null) {
			newGroupId = entity.groupId;
		}

		boolean checkForUnique = true;
		if (newName.equals(entity.name) && (newGroupId == entity.groupId)) {
			// changing case of the display name
			checkForUnique = false;
		}

		if (newRestricted == null)
			newRestricted = entity.restricted;

		if (newEnabled == null)
			newEnabled = entity.enabled;

		if (checkForUnique) {
			List<Key<ListEntity>> keys = ofy(namespace).load()
					.type(ListEntity.class).filter("name", newName)
					.filter("groupId", entity.groupId).keys().list();

			if (keys.size() != 0)
				throw new APIException(Status.ERROR_RESOURCE_ALREADY_EXISTS,
						"There is already another list with name ["
								+ newDisplayName + "] for group ["
								+ entity.groupId + "]");
		}

		entity.displayName = newDisplayName;
		entity.name = newName;
		entity.groupId = newGroupId;
		entity.enabled = newEnabled;
		entity.restricted = newRestricted;

		ofy(namespace).save().entity(entity);
		return entity.toProp();
	}

	static void delete(String namespace, long listId) {
		ensureNotNull(namespace, "namespace is null");
		ensure(namespace.length() != 0, "namespace is empty");
		ensure(listId != 0, "listId is 0");

		ListEntity entity = safeGet(namespace, listId);

		if (entity.enabled)
			throw new APIException().status(Status.ERROR_OPERATION_NOT_ALLOWED)
					.message("List should be disabled before deleting");
		
		ofy(namespace).delete().entity(entity).now();
	}
}
